package com.dji.sample.manage.service.impl;

import com.dji.sample.common.error.CommonErrorEnum;
import com.dji.sample.common.util.SpringBeanUtilsTest;
import com.dji.sample.manage.model.dto.ProductConfigDTO;
import com.dji.sample.manage.model.enums.CustomizeConfigScopeEnum;
import com.dji.sdk.cloudapi.config.ProductConfigResponse;
import com.dji.sdk.cloudapi.config.RequestsConfigRequest;
import com.dji.sdk.cloudapi.config.api.AbstractConfigService;
import com.dji.sdk.mqtt.MqttReply;
import com.dji.sdk.mqtt.requests.TopicRequestsRequest;
import com.dji.sdk.mqtt.requests.TopicRequestsResponse;
import org.springframework.messaging.MessageHeaders;
import org.springframework.stereotype.Service;

import java.util.Optional;

/**
 * 配置请求处理服务实现类。
 * 该类用于处理设备连接云平台时的License校验和配置请求，是上云流程中关键的第一步。
 * 当设备（如DJI Pilot 2或DJI Dock）连接到MQTT并发送config方法请求时，
 * 本服务会根据请求数据返回包含appId、appKey和appLicense的配置信息。
 * 这些凭证会被设备用于验证是否有权与此云平台通信。
 * 
 * 时序图中对应步骤：
 * 1. 设备发送License校验请求：thing/product/{gateway_sn}/requests, Method: config
 * 2. 云平台返回License信息：thing/product/{gateway_sn}/requests_reply, Method: config
 * 3. 设备验证License，若成功则继续组织绑定流程，失败则断开连接
 * 
 * @author sean
 * @version 1.3
 * @date 2022/11/10
 */
@Service
public class RequestConfigContext extends AbstractConfigService {

    /**
     * 处理配置请求的方法，实现了AbstractConfigService中的抽象方法。
     * 当设备发送config方法请求时，该方法被调用，返回包含License信息的响应。
     * 
     * 处理流程：
     * 1. 验证请求中的配置范围(configScope)是否有效
     * 2. 获取对应范围的配置服务实现类
     * 3. 从配置服务中获取配置信息(appId、appKey、appLicense等)
     * 4. 返回包含配置信息的响应
     * 
     * @param request 包含配置请求信息的对象，包括配置类型和配置范围
     * @param headers 消息头信息
     * @return 包含应用ID、Key和License的配置响应
     */
    @Override
    public TopicRequestsResponse<ProductConfigResponse> requestsConfig(TopicRequestsRequest<RequestsConfigRequest> request, MessageHeaders headers) {
        // 获取请求数据
        RequestsConfigRequest configReceiver = request.getData();
        // 根据请求的配置范围查找对应的枚举值
        Optional<CustomizeConfigScopeEnum> scopeEnumOpt = CustomizeConfigScopeEnum.find(configReceiver.getConfigScope().getScope());
        // 如果配置范围无效，返回参数错误
        if (scopeEnumOpt.isEmpty()) {
            return new TopicRequestsResponse().setData(MqttReply.error(CommonErrorEnum.ILLEGAL_ARGUMENT));
        }

        // 获取配置服务的Bean实例，并获取配置信息
        ProductConfigDTO config = (ProductConfigDTO) SpringBeanUtilsTest.getBean(scopeEnumOpt.get().getClazz()).getConfig();
        // 创建并返回配置响应，包含NTP服务器地址和应用凭证信息
        return new TopicRequestsResponse<ProductConfigResponse>().setData(
                new ProductConfigResponse()
                        .setNtpServerHost(config.getNtpServerHost())
                        .setAppId(config.getAppId())
                        .setAppKey(config.getAppKey())
                        .setAppLicense(config.getAppLicense()));
    }
}
